
import { MoonRecordInventory } from '../compute/moonRecords';
import { MoonRecordView } from '../view/moon_record/moonRecord';

function createPendant(context) {
  let t0 = new P(context);
  global.t0 = t0;

  let pendant = new context.Pendant({
    require : ['zrender'],
    init : (libs, args) => t0.init(libs, args),
    destroy : () => t0.destroy(),

    // custom function
    collectInfo : () => t0.collectInfo(),
    onMessage : (key, value) => t0.onMessage(key, value),
  });
  t0.sendStatus = () => pendant.sendStatus();
  return pendant;
}

class P {
  constructor(context) {
    this.context = context;
    this.moonRecords = new MoonRecordInventory({ assetPath: context.assetPath });
  }

  init(libs, args) {
    this.view = new MoonRecordView({
      context: this.context,
      dom: args.dom,
      zrender: libs.zrender,
    });
    this.updateByParams(args.params);

    this.view.on('view/resize', (_, value) => {
      this.arg.view.width = value.width;
      this.arg.view.height = value.height;
      this.sendStatus();
    });
    this.view.startTick();

    this.asyncLoadRecords()
        .then(p => this.view.setRecords(p.list, p.showFirstSummary));
  }

  asyncLoadRecords() {
    return this.moonRecords.load()
      .then(list => {
        switch(this.arg.method) {
          case "latest":
            return { list: this.filterLatestRecords(list), showFirstSummary: false };
          case "year":
            return { list: this.filterRecordsByYear(list), showFirstSummary: true };
          case "country":
            return { list: this.filterRecordsByCountry(list), showFirstSummary: true };
          case "all": default:
            return { list, showFirstSummary: true };
        }
      });
  }

  /**
   * @param {MoonRecord[]} list
   */
  filterLatestRecords(list) {
    let { offset, count } = this.arg.params;

    let startIdx = list.length - (offset + count);
    if (startIdx <= 0) {
      startIdx = 0;
    }
    let endIdx = list.length - offset;
    if (endIdx <= 0) {
      endIdx = 0;
    }
    return list.slice(startIdx, endIdx);
  }

  /**
   * @param {MoonRecord[]} list
   */
  filterRecordsByYear(list) {
    let { from, to } = this.arg.params;
    return list.filter(r => r.year >= from && r.year <= to);
  }

  /**
   * @param {MoonRecord[]} list
   */
  filterRecordsByCountry(list) {
    /** @type {string[]} */
    let countries = this.arg.params.countries;
    return this.filterLatestRecords(list.filter(r => countries.some(c => r.countries.includes(c))));
  }

  arg = {
    format : "planetaryExploration/moon",
    method : "all",
    params : {
      // offset : 0,
      // count : 20,
      // from : 2000,
      // to : 2020,
      // countries : [],
    },
    view : {
      width : 400,
      height : 400,
    },
  };

  collectInfo() {
    return this.arg;
  }

  // onMessage('update', {method:'country', params:{countries: ['CN', 'USA'], count: 50}})
  // onMessage('update', {method:'latest', params:{offset: 0, count: 50}})
  // onMessage('update', {method:'year', params:{from: 1980, to: 2020}})
  onMessage(key, value) {
    switch (key) {
			case 'update': {
        let success = this.onUpdate(value.method, value.params);
        if (success) {
          this.asyncLoadRecords()
            .then(params => this.view.setRecords(params.list, params.showFirstSummary));
        } else {
          console.error('update 失败', value.method, value.params);
        }
				this.sendStatus();
      } return;

      // onMessage('print', {bg: 'transparent'})
      case 'print': {
        if (typeof(value.bg) == 'string') {
          this.view.setBgColor(value.bg);
        }
				this.sendStatus();
      } return;
		}
		console.log("moon_record 收到命令", key, value);
  }

  updateByParams(initParam) {
    if (initParam == null || initParam.mode == null) {
      return;
    }

    const params = {
      offset : (initParam.offset == null) ? null : parseInt(initParam.offset),
      count : (initParam.count == null) ? null : parseInt(initParam.count),
      from : (initParam.fromYear == null) ? null : parseInt(initParam.fromYear),
      to : (initParam.toYear == null) ? null : parseInt(initParam.toYear),
      countries : typeof(initParam.countries) == 'string' ? initParam.countries.split(',') : [],
    };
    this.onUpdate(initParam.mode, params);
  }

  /**
   * @param {string} method
   * @param {object} params
   * @returns 修改是否成功
   */
  onUpdate(method, params) {
    switch (method) {
      case 'latest':{
        let offset = params.offset == null ? 0 : parseInt(params.offset);
        let count = params.count == null ? 20 : parseInt(params.count);
        if (offset < 0 || count <= 0 || !isFinite(offset) || !isFinite(count)) {
          return false;
        }
        this.arg.method = 'latest';
        this.arg.params = { offset, count };
      } return true;

      case 'year':{
        let from = parseInt(params.from);
        let to = parseInt(params.to);
        if (!isFinite(from) || !isFinite(to) || from < 1950 || to < 1950 || from > to) {
          return false;
        }
        from = ((from / 10) | 0) * 10;
        to = ((to / 10) | 0) * 10 + 9;

        this.arg.method = 'year';
        this.arg.params = { from, to };
      } return true;

      case 'country': {
        let countries = params.countries;
        if (!(countries instanceof Array)) return false;
        if (!countries.every(c => typeof(c) == 'string')) return false;

        let offset = params.offset == null ? 0 : parseInt(params.offset);
        let count = params.count == null ? 20 : parseInt(params.count);
        if (offset < 0 || count <= 0 || !isFinite(offset) || !isFinite(count)) {
          return false;
        }
        this.arg.method = 'country';
        this.arg.params = { offset, count, countries };
      } return true;

      case 'all': {
        this.arg.method = 'all';
        this.arg.params = { };
      } return true;

      default: return false;
    }
  }

  destroy() {
    this.view.destroy();
  }
}

export default createPendant;
